home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / src / unexnext.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-26  |  8.8 KB  |  303 lines

  1. /* Dump Emacs in macho format.
  2.    Copyright (C) 1990-1993 Free Software Foundation, Inc.
  3.    Written by Bradley Taylor (btaylor@next.com).
  4.  
  5. This file is part of XEmacs.
  6.  
  7. XEmacs is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. XEmacs is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with XEmacs; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /* Synched up with:  NeXT port */
  22.  
  23. #include <stdio.h>
  24. #include <libc.h>
  25. #include <nlist.h>
  26. #include <mach/mach.h>
  27. #include <mach-o/ldsyms.h>
  28. #include <mach-o/loader.h>
  29.  
  30. int malloc_cookie;
  31.  
  32. static void fatal_unexec(char *format, ...)
  33.    {
  34.    va_list ap;
  35.    
  36.    va_start(ap, format);
  37.    fprintf(stderr, "unexec: ");
  38.    vfprintf(stderr, format, ap);
  39.    fprintf(stderr, "\n");
  40.    va_end(ap);
  41.    exit(1);
  42.    }
  43.  
  44. static void mcopy(int ffd,int tfd,
  45.                   unsigned long fpos,unsigned long tpos,unsigned long len)
  46.    {
  47.    if ((ffd==-1)&&(tfd==-1))
  48.       {
  49.       char *f,*t,*e;
  50.       if (fpos>tpos)
  51.          {
  52.          f=(char *)fpos;
  53.          t=(char *)tpos;
  54.          e=(char *)(fpos+len);
  55.          while(f<e) *t++=*f++;
  56.          }
  57.       else if (tpos>fpos)
  58.          {
  59.          f=(char *)(fpos+len);
  60.          t=(char *)(tpos+len);
  61.          e=(char *)fpos;
  62.          while(f>e) *--t=*--f;         
  63.          }   
  64.       }
  65.    else if (ffd==-1)
  66.       {
  67.       if (lseek(tfd,tpos,L_SET)<0)
  68.          fatal_unexec("cannot seek target");
  69.       if (write(tfd,(void *)fpos,len)!=len)
  70.          fatal_unexec("cannot write target");
  71.       }
  72.    else if (tfd==-1)
  73.       {
  74.       if (lseek(ffd,fpos,L_SET)<0)
  75.          fatal_unexec("cannot seek source");
  76.       if (read(ffd,(void *)tpos,len)!=len)
  77.          fatal_unexec("cannot read source");
  78.       }
  79.    else
  80.       {
  81.       int bread;
  82.       char *buf=alloca(1<<16);
  83.       
  84.       if (lseek(ffd,fpos,L_SET)<0)
  85.          fatal_unexec("cannot seek source");
  86.       
  87.       if (lseek(tfd,tpos,L_SET)<0)
  88.          fatal_unexec("cannot seek target");
  89.       
  90.       while((len>0) && (bread=read(ffd,buf,MIN(1<<16,len)))>0)
  91.          {
  92.          if (bread<0)
  93.             fatal_unexec("cannot read source");
  94.          if (write(tfd,buf,bread)!=bread)
  95.             fatal_unexec("cannot write target");
  96.          len-=bread;
  97.          }
  98.       }
  99.    }
  100.  
  101. static void unexec_doit(int infd,int outfd)
  102.    {
  103.    int i,j,hpos,opos;
  104.    extern int malloc_freezedry(void);
  105.    struct region
  106.       {
  107.       struct region *next;
  108.       unsigned long addr;
  109.       unsigned long size;
  110.       vm_prot_t prot;
  111.       vm_prot_t mprot;
  112.       } *regions=0,*cregion,**pregions;
  113.    struct mach_header mh;
  114.    struct segment_command *lc,*sp;
  115.    struct symtab_command *st;
  116.    struct section *sect;
  117.  
  118.    malloc_cookie=malloc_freezedry();
  119.    
  120.       {
  121.       vm_task_t task=task_self();
  122.       vm_address_t addr;
  123.       vm_size_t size;
  124.       vm_prot_t prot,mprot;
  125.       vm_inherit_t inhe;
  126.       boolean_t shrd;
  127.       port_t name;
  128.       vm_offset_t offset;
  129.       
  130.       for(addr=VM_MIN_ADDRESS,pregions=®ions;
  131.           vm_region(task,&addr,&size,&prot,&mprot,
  132.                     &inhe,&shrd,&name,&offset)==KERN_SUCCESS;
  133.           addr += size)
  134.          {
  135.          (*pregions)=alloca(sizeof(struct region));
  136.          (*pregions)->addr=addr;
  137.          (*pregions)->size=size;
  138.          (*pregions)->prot=prot;
  139.          (*pregions)->mprot=mprot;
  140.          (*pregions)->next=0;
  141.          pregions=&((*pregions)->next);
  142.          }
  143.       }
  144.    
  145.    for(cregion=regions;cregion;cregion=cregion->next)
  146.       while ((cregion->next) &&
  147.              (cregion->next->addr==cregion->addr+cregion->size) &&
  148.              (cregion->next->prot==cregion->prot) &&
  149.              (cregion->next->mprot==cregion->mprot))
  150.          {
  151.          cregion->size += cregion->next->size;
  152.          cregion->next = cregion->next->next;
  153.          }
  154.  
  155.    mcopy(infd,-1,0,(unsigned long) &mh,sizeof(mh));
  156.    lc=alloca(mh.sizeofcmds);
  157.    mcopy(infd,-1,sizeof(mh),(unsigned long) lc,mh.sizeofcmds);
  158.    
  159.    for(pregions=®ions;*pregions;)
  160.       {
  161.       if (!((*pregions)->prot&VM_PROT_WRITE)
  162.           || ((*pregions)->addr>=0x3000000))
  163.          goto kill_region;
  164.       
  165.       for(sp=lc,i=0;
  166.           i<mh.ncmds;
  167.           i++,sp=(struct segment_command *)(((char *)sp)+sp->cmdsize))
  168.          {
  169.          unsigned long ob,oe;
  170.          if (sp->cmd!=LC_SEGMENT||(strcmp(sp->segname,SEG_DATA)==0)) continue;
  171.          ob=MAX((*pregions)->addr,sp->vmaddr);
  172.          oe=MIN((*pregions)->addr+(*pregions)->size,sp->vmaddr+sp->vmsize);
  173.          if (ob >= oe) continue;
  174.          if (ob==(*pregions)->addr)
  175.             if (oe==(*pregions)->addr+(*pregions)->size)
  176.                {
  177.                goto kill_region;
  178.                }
  179.             else
  180.                {
  181.                (*pregions)->addr=oe;
  182.                (*pregions)->size-=(oe-ob);
  183.                }
  184.          else
  185.             if (oe==(*pregions)->addr+(*pregions)->size)
  186.                {
  187.                (*pregions)->size-=(oe-ob);
  188.                }
  189.             else
  190.                {
  191.                cregion=alloca(sizeof(*cregion));
  192.                cregion->addr=oe;
  193.                cregion->size=((*pregions)->addr+(*pregions)->size)-oe;
  194.                cregion->prot=(*pregions)->prot;
  195.                cregion->mprot=(*pregions)->mprot;
  196.                cregion->next=(*pregions)->next;
  197.                (*pregions)->size=ob-(*pregions)->addr;
  198.                (*pregions)->next=cregion;
  199.                }
  200.          }
  201.       pregions=&((*pregions)->next);
  202.       continue;
  203.     kill_region:
  204.       *pregions=(*pregions)->next;
  205.       }
  206.  
  207.    for(sp=lc,i=mh.ncmds,hpos=sizeof(mh),opos=0;
  208.        i>0;
  209.        i--,sp=(struct segment_command *)(((char *)sp)+sp->cmdsize))
  210.       switch (sp->cmd)
  211.          {
  212.        case LC_SEGMENT:
  213.          if (strcmp(sp->segname,SEG_DATA)==0)
  214.             {
  215.             mh.ncmds--;
  216.             j=sp->cmdsize;
  217.             while (regions)
  218.                {
  219.                mcopy(-1,outfd,regions->addr,opos,regions->size);
  220.                sp->cmd=LC_SEGMENT;
  221.                sp->cmdsize=sizeof(*sp);
  222.                strncpy(sp->segname,SEG_DATA,sizeof(sp->segname));
  223.                sp->vmaddr=regions->addr;
  224.                sp->vmsize=regions->size;
  225.                sp->filesize=regions->size;
  226.                sp->maxprot=regions->prot;
  227.                sp->initprot=regions->mprot;
  228.                sp->nsects=0;
  229.                sp->flags=0;
  230.                sp->fileoff=opos;
  231.                opos+=sp->filesize;
  232.                mcopy(-1,outfd,(unsigned long)sp,hpos,sp->cmdsize);
  233.                hpos+=sp->cmdsize;
  234.                mh.ncmds++;
  235.                regions=regions->next;
  236.                }
  237.             sp->cmdsize=j;
  238.             regions=0;
  239.             }
  240.          else if (strcmp(sp->segname,SEG_LINKEDIT)==0)
  241.             {
  242.             mh.ncmds--;
  243.             }
  244.          else
  245.             {
  246.             mcopy(infd,outfd,sp->fileoff,opos,sp->filesize);
  247.             sect=(struct section *) (((char *)sp)+sizeof(*sp));
  248.             for(j=0;j<sp->nsects;j++)
  249.                {
  250.                if (sect[j].offset!=0)
  251.                   sect[j].offset=(sect[j].offset-sp->fileoff)+opos;
  252.                if (sect[j].reloff!=0)
  253.                   sect[j].reloff=(sect[j].reloff-sp->fileoff)+opos;
  254.                }
  255.             sp->fileoff=opos;
  256.             opos+=sp->filesize;
  257.             mcopy(-1,outfd,(unsigned long)sp,hpos,sp->cmdsize);
  258.             hpos+=sp->cmdsize;
  259.             }
  260.      break;
  261.        case LC_SYMTAB:
  262.          st=(struct symtab_command *)sp;
  263.          
  264.          mcopy(infd,outfd,st->symoff,opos,st->nsyms*sizeof(struct nlist));
  265.          st->symoff=opos;
  266.          opos+=sizeof(struct nlist)*st->nsyms;
  267.          
  268.          mcopy(infd,outfd,st->stroff,opos,st->strsize);
  269.          ((struct symtab_command *)sp)->stroff=opos;
  270.          opos+=((struct symtab_command *)sp)->strsize;
  271.        default:
  272.          mcopy(-1,outfd,(unsigned long)sp,hpos,sp->cmdsize);
  273.          hpos+=sp->cmdsize;
  274.          }
  275.    mh.sizeofcmds=hpos-sizeof(mh);
  276.    mcopy(-1,outfd,(unsigned long) &mh,0,sizeof(mh));
  277.    }
  278.  
  279. void unexec(char *outfile,char *infile)
  280.    {
  281.    char tmpfile[MAXPATHLEN];
  282.    int infd,outfd;
  283.    
  284.    if ((infd=open(infile, O_RDONLY, 0))<0)
  285.       fatal_unexec("cannot open input file `%s'", infile);
  286.  
  287.    strcpy(tmpfile,outfile);
  288.    strcat(tmpfile,"-temp");
  289.    
  290.    if ((outfd=open(tmpfile, O_RDWR|O_TRUNC|O_CREAT, 0755))<0)
  291.       fatal_unexec("cannot open temporary output file `%s'",tmpfile);
  292.  
  293.    unexec_doit(infd,outfd);
  294.  
  295.    close(infd);
  296.    close(outfd);
  297.    if (rename(tmpfile, outfile)<0)
  298.       {
  299.       unlink(tmpfile);
  300.       fatal_unexec("cannot rename `%s' to `%s'", tmpfile, outfile);
  301.       }  
  302.    }
  303.